<template>
	<el-card class="box-card" v-loading="tableLoading" element-loading-text="拼命加载中...">
		<div class="operating-but">
			<hasRole v-for="item in tableConfig.globalOperate" :key="item.name" :permi="item.role">
				<template v-if="item.enable == 1">
					<el-button
						@click="tableConfig.handlerOperate(item, selectionData)"
						:type="item.color"
						:disabled="selectionData.length !== 1"
						plain
						size="mini"
						:icon="item.icon"
					>
						{{ item.name }}
					</el-button>
				</template>
				<template v-else-if="item.enable == 2">
					<el-button
						@click="tableConfig.handlerOperate(item, selectionData)"
						:type="item.color"
						:disabled="selectionData.length === 0"
						plain
						size="mini"
						:icon="item.icon"
					>
						{{ item.name }}
					</el-button>
				</template>
				<el-button
					v-else
					@click="tableConfig.handlerOperate(item, selectionData)"
					:type="item.color"
					plain
					size="mini"
					:icon="item.icon"
				>
					{{ item.name }}
				</el-button>
			</hasRole>
		</div>
		<el-table
			:data="resPageData.list"
			:height="tableConfig.tableHeight"
			:stripe="tableConfig.stripe"
			:border="tableConfig.border"
			:size="tableConfig.size"
			:show-header="tableConfig.showHeader"
			:span-method="spanMethod"
			@select-all="selectAll"
			@sort-change="sortChange"
			row-key="id"
			:default-expand-all="tableConfig.expandAll"
			:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
		>
			<el-table-column
				v-for="item in tableConfig.columns"
				:type="item.type"
				:key="item.field"
				:prop="item.field"
				:label="item.title"
				:width="item.width"
				:fixed="item.fixed"
				:show-overflow-tooltip="item.overflowTooltip"
				:align="item.align || 'center'"
				:class-name="item.className"
				:label-class-name="item.labelClassName"
				:sortable="item.sortable"
			>
				<template v-slot:header>
					<slot :name="`${item.field}Header`">
						<span @click="handlerHeader(item)">{{ item.title }}</span>
					</slot>
				</template>
				<template v-slot="scope">
					<span v-if="item.type == 'index'">
						{{
							tableConfig.pageNumber == 1
								? scope.$index + 1
								: (tableConfig.pageNumber - 1) * tableConfig.pageSize + scope.$index + 1
						}}
					</span>
					<el-checkbox
						@change="checkboxChange"
						v-if="item.type == 'selection'"
						v-model="scope.row['selection']"
					></el-checkbox>
					<el-radio
						@change="radioChange(scope.$index)"
						v-if="item.type == 'radio'"
						:label="true"
						v-model="scope.row['selection']"
					>
						{{ '' }}
					</el-radio>
					<slot :name="item.field" :row="scope.row">
						<span @click="handlerTable(scope.row)">
							{{
								item.formatter
									? item.formatter(scope.row[item.field], scope.row)
									: scope.row[item.field]
							}}
						</span>
					</slot>
				</template>
			</el-table-column>
			<el-table-column
				:width="tableConfig.operateWidth"
				v-if="tableConfig.operate.length !== 0"
				fixed="right"
				:align="tableConfig.operateAlign"
				label="操作"
			>
				<template v-slot="scope">
					<hasRole v-for="(item, i) in tableConfig.operate" :key="i" :permi="item.role">
						<el-button
							@click="tableConfig.handlerOperate(item, [scope.row])"
							:type="item.type"
							size="mini"
							:icon="item.icon"
						>
							{{ item.name }}
						</el-button>
					</hasRole>
				</template>
			</el-table-column>
		</el-table>
		<el-pagination
			v-if="tableConfig.hasPage"
			id="pagination"
			background
			:page-size="tableConfig.pageSize"
			:total="resPageData.total"
			v-model:current-page="tableConfig.pageNumber"
			layout="sizes, prev, pager, next, jumper, ->, total, slot"
			:page-sizes="tableConfig.pageSizes"
			@size-change="handlerSizeChange"
			@current-change="handlerCurrentChange"
		></el-pagination>
	</el-card>
</template>

<script>
	import { ref, reactive, onMounted, onUnmounted } from 'vue';
	import { debounce } from '@/utils/Tools';
	export default {
		props: {
			config: {
				type: Object,
				required: true,
			},
		},
		setup(ctx) {
			let tableConfig = reactive({
				initApi: true, // 是否自动调用
				reqApiMethod: () => {}, // api 需要返回Promise
				handlerHeader: () => {}, // 表头点击
				handlerTable: () => {}, // 表格点击
				handlerSelectionChange: () => {}, // 单选/多选 触发
				mergeTable: () => {}, // 表格合并
				responseHandler: list => list, // 格式接口返回的数据
				queryParams: params => params, // 格式接口入参的数据
				handlerOperate: () => {}, // 按钮操作项事件
				expandAll: false, // 是否展开所有
				tableHeight: null, // table高
				showHeader: true, // 是否显示表头
				size: 'medium', // Table 的尺寸 medium / small / mini
				stripe: true, // 隔行变色
				border: false, // 是否带有纵向边框
				hasPage: true, // 是否分页
				pageNumber: 1, // 当前的页数
				pageSize: 10, // 每页展示条数
				pageSizes: [10, 20, 30], // 选择每一个展示的条数
				/**
				 * 全局按钮操作项:顶部位置
				 *  butType 唯一key
				 *  type: '', // 类型
				 *  enable: '' 操作按钮禁用状态 1 选中一个启用 2 选中一个或者多个启用
				 *  name: "", // 文字
				 *  color: "", // 颜色
				 *  role: [], // 权限
				 *  icon: "", // 图标
				 */
				globalOperate: [],
				operateWidth: 120, // 列表操作项宽
				operateAlign: 'center', // 列表操作项对齐方式 left|center|right
				/**
				 * 列表按钮操作项
				 *  butType 唯一key
				 *  type: '', // 类型
				 *  name: "", // 文字
				 *  color: "", // 颜色
				 *  role: [], // 权限
				 *  icon: "", // 图标
				 */
				operate: [], // 列表操作项
				/**
				 * 表头信息
				 * type:expand 展开 |index 序号|selection 多选|radio 单选
				 * title: 表头标题
				 * field: 渲染列表的key
				 * width: 表格宽
				 * formatter: 格式化函数
				 * overflowTooltip：超出文字展示...,
				 * align: 对齐方式
				 * className: 列的 className
				 * labelClassName: 当前列标题的自定义类名
				 * sortable:'custom' // 排序
				 * field+Header: 表头插槽
				 * field: 表格插槽
				 */
				columns: [],
				...ctx.config,
			});
			let tableLoading = ref(false);
			// 列表数据
			let resPageData = ref({
				list: [],
				total: 0,
			});
			// 选择的数据
			let selectionData = ref([]);

			// 获取列表数据
			let fetchData = async ({ isResetPageNumber = false } = {}) => {
				tableLoading.value = true;
				selectionData.value = [];
				return new Promise(resolve => {
					// 搜索重置页数
					if (isResetPageNumber) {
						tableConfig.pageNumber = 1;
					}
					// 过滤空数据
					let searchParams = {};
					Object.keys(ctx.config.searchParams).forEach(key => {
						if (
							ctx.config.searchParams[key] !== '' &&
							ctx.config.searchParams[key] !== 'null' &&
							ctx.config.searchParams[key] !== 'undefined' &&
							ctx.config.searchParams[key] !== null &&
							ctx.config.searchParams[key] !== undefined
						) {
							searchParams[key] = ctx.config.searchParams[key];
						}
					});
					let queryForm = tableConfig.queryParams({
						pageNumber: tableConfig.pageNumber,
						pageSize: tableConfig.pageSize,
						...searchParams,
					});
					// 是否分页
					if (!tableConfig.hasPage) {
						delete queryForm.pageNumber;
						delete queryForm.pageSize;
					}
					tableConfig
						.reqApiMethod(queryForm)
						.then(res => {
							tableLoading.value = false;
							resPageData.value = tableConfig.responseHandler(res);
							resPageData.value.list &&
								resPageData.value.list.forEach(item => {
									item.selection = false;
								});
							resolve();
						})
						.catch(() => {
							tableLoading.value = false;
							resolve();
						});
				});
			};

			// 全选/反选
			let selectAll = payload => {
				resPageData.value.list.forEach(item => (item.selection = payload.length !== 0));
				handlerSelectionChange(resPageData.value.list);
			};
			// 单选
			let radioChange = index => {
				resPageData.value.list.forEach((item, i) => (item.selection = i === index));
				handlerSelectionChange(resPageData.value.list);
			};
			// 复选
			let checkboxChange = () => {
				handlerSelectionChange(resPageData.value.list);
			};
			// 排序
			let sortChange = column => {
				console.log(column);
			};

			// 每页条数改变
			let handlerSizeChange = val => {
				tableConfig.pageSize = val;
				fetchData();
			};
			// 页数改变
			let handlerCurrentChange = val => {
				tableConfig.pageNumber = val;
				fetchData();
			};

			// 表头点击操作
			let handlerHeader = payload => {
				tableConfig.handlerHeader(payload);
			};
			// table单元格点击
			let handlerTable = payload => {
				tableConfig.handlerTable(payload);
			};

			// 表格跨行
			let spanMethod = ({ row, column, rowIndex, columnIndex }) => {
				return tableConfig.mergeTable({ row, column, rowIndex, columnIndex });
			};

			// 单选/多选 触发
			let handlerSelectionChange = () => {
				let res = resPageData.value.list.filter(item => item.selection);
				selectionData.value = res;
				tableConfig.handlerSelectionChange(res);
			};

			if (tableConfig.initApi) {
				fetchData();
			}

			let screenDom = 0;
			let headerDom = 0;
			let searchDom = 0;
			let paginationDom = 0;
			// 动态计算列表高度
			let onResize = () => {
				let headerHeight = headerDom.clientHeight;
				let searchHeight = searchDom.clientHeight;
				let paginationHeight = paginationDom.clientHeight;
				tableConfig.tableHeight =
					screenDom - (headerHeight + searchHeight + paginationHeight + 120);
			};

			onMounted(() => {
				screenDom = document.body.clientHeight;
				headerDom = document.querySelector('#header') || { clientHeight: 0 };
				searchDom = document.querySelector('#search') || { clientHeight: 0 };
				paginationDom = document.querySelector('#pagination') || {
					clientHeight: 0,
				};
				onResize();
				window.addEventListener('resize', debounce(onResize, 100));
			});

			// 解绑
			onUnmounted(() => {
				window.removeEventListener('resize', onResize);
			});

			return {
				tableConfig,
				tableLoading,
				resPageData,
				selectAll,
				checkboxChange,
				radioChange,
				sortChange,
				handlerSizeChange,
				handlerCurrentChange,
				handlerHeader,
				handlerTable,
				spanMethod,
				selectionData,
				fetchData,
			};
		},
	};
</script>

<style lang="scss" scoped>
	.el-pagination {
		padding-top: 10px;
	}
	.operating-but {
		display: flex;
	}
</style>
